﻿using ICSharpCode.SharpZipLib.Checksum;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;

namespace housingsafety.server.Helpers
{
    /// <summary>
    /// 压缩辅助类
    /// </summary>
    public class ZipHelper
    {
        /// <summary>
        /// Zip文件压缩
        /// ZipOutputStream：相当于一个压缩包；
        /// ZipEntry：相当于压缩包里的一个文件；
        /// 以上两个类是SharpZipLib的主类。
        /// </summary>
        /// <param name="sourceFileLists"></param>
        /// <param name="saveFile">压缩文件保存的目录</param>
        /// <param name="compression">压缩级别0-9</param>
        public static void ZipCompress(List<string> sourceFileLists, string saveFile, int compression)
        {
            if (compression < 0 || compression > 9)
            {
                return;
            }

            if (!Directory.Exists(new FileInfo(saveFile).Directory.ToString()))
            {
                return;
            }

            Crc32 crc32 = new Crc32();
            using (ZipOutputStream stream = new ZipOutputStream(File.Create(saveFile)))
            {
                stream.SetLevel(compression);// 设置压缩等级，等级越高压缩效果越明显，但占用CPU也会更多

                ZipEntry entry;
                for (int i = 0; i < sourceFileLists.Count; i++)
                {
                    entry = new ZipEntry(Path.GetFileName(sourceFileLists[i]));
                    entry.DateTime = DateTime.Now;
                    entry.IsUnicodeText = true;
                    using (FileStream fs = File.OpenRead(sourceFileLists[i]))
                    {
                        byte[] buffer = new byte[fs.Length];
                        fs.Read(buffer, 0, buffer.Length);
                        entry.Size = fs.Length;
                        crc32.Reset();
                        crc32.Update(buffer);
                        entry.Crc = crc32.Value;
                        stream.PutNextEntry(entry);
                        stream.Write(buffer, 0, buffer.Length);
                    }
                    stream.CloseEntry();
                }
            }
        }

        /// <summary>
        /// Zip文件压缩
        /// ZipOutputStream：相当于一个压缩包；
        /// ZipEntry：相当于压缩包里的一个文件；
        /// 以上两个类是SharpZipLib的主类。
        /// </summary>
        /// <param name="sourceFileLists"></param>
        /// <param name="compression">压缩级别0-9</param>
        /// <returns></returns>
        public static Stream ZipCompressStream(List<string> sourceFileLists, int compression)
        {
            // 创建压缩流
            var ms = new MemoryStream();
            if (compression >= 0 || compression <= 9)
            {
                Crc32 crc32 = new Crc32();
                using (ZipOutputStream zipStream = new ZipOutputStream(ms))
                {
                    zipStream.SetLevel(compression);// 设置压缩等级，等级越高压缩效果越明显，但占用CPU也会更多

                    ZipEntry entry;
                    for (int i = 0; i < sourceFileLists.Count; i++)
                    {
                        entry = new ZipEntry(Path.GetFileName(sourceFileLists[i]));
                        entry.DateTime = DateTime.Now;
                        entry.IsUnicodeText = true;
                        using (FileStream fs = File.OpenRead(sourceFileLists[i]))
                        {
                            byte[] buffer = new byte[fs.Length];
                            fs.Read(buffer, 0, buffer.Length);
                            entry.Size = fs.Length;
                            crc32.Reset();
                            crc32.Update(buffer);
                            entry.Crc = crc32.Value;
                            zipStream.PutNextEntry(entry);
                            zipStream.Write(buffer, 0, buffer.Length);
                        }
                        zipStream.CloseEntry();
                    }

                    zipStream.IsStreamOwner = false;
                    zipStream.Finish();
                    zipStream.Close();
                }

                ms.Position = 0;
            }

            return ms;
        }

        /// <summary>
        /// unZip文件解压缩
        /// </summary>
        /// <param name="sourceFile">要解压的文件</param>
        /// <param name="path">要解压到的目录</param>
        public static void ZipDeCompress(string sourceFile, string path)
        {
            if (!File.Exists(sourceFile))
            {
                throw new ArgumentException("要解压的文件不存在。");
            }
            if (!Directory.Exists(path))
            {
                throw new ArgumentException("要解压到的目录不存在！");
            }
            using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourceFile)))
            {
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    string fileName = System.IO.Path.GetFileName(theEntry.Name);
                    if (fileName != string.Empty)
                    {
                        using (FileStream streamWriter = File.Create(path + @"\" + theEntry.Name))
                        {
                            int size = 2048;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
